package com.faner.fast.upms.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.faner.fast.annotation.AnonymousAccess;
import com.faner.fast.annotation.SysLog;
import com.faner.fast.base.PageDTO;
import com.faner.fast.security.service.FastOnlineUserService;
import com.faner.fast.security.service.FastUser;
import com.faner.fast.upms.domain.dto.ChangePasswordDTO;
import com.faner.fast.upms.domain.dto.LoginDTO;
import com.faner.fast.upms.domain.dto.SysUserDTO;
import com.faner.fast.upms.domain.vo.SysUserVO;
import com.faner.fast.upms.mapper.SysUserMapper;
import com.faner.fast.upms.model.SysUserDO;
import com.faner.fast.upms.service.SysUserService;
import com.faner.fast.upms.util.FastSecurityUtils;
import com.faner.fast.util.JwtTokenUtil;
import com.faner.fast.util.PageUtil;
import com.faner.fast.util.R;
import com.faner.fast.util.ValueUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.Positive;
import java.util.HashMap;
import java.util.Map;

@Validated
@RestController
@RequiredArgsConstructor
@Api(value = "user", tags = "系统-用户管理模块")
@ApiSupport(order = 10,author = "faner")
public class UserController {

    private final SysUserService sysUserService;
    private final UserDetailsService fastUserDetailsService;
    private final JwtTokenUtil jwtTokenUtil;
    private final FastOnlineUserService fastOnlineUserService;
    /**
     * 获取当前用户全部信息
     * @return 用户信息
     */
    @ApiOperation(value = "获取当前登录用户信息")
    @ApiOperationSupport(order = 10,author = "faner")
    @GetMapping(value = "/user/info")
    public R info() {
        String username = FastSecurityUtils.getUser().getUsername();
        SysUserDO user = sysUserService.getOne(Wrappers.<SysUserDO>query().lambda().eq(SysUserDO::getUsername, username));
        if (user == null) {
            return R.failed("获取当前用户信息失败");
        }
        return R.ok(sysUserService.getUserInfo(user));
    }
    /**
     * 分页查询用户
     * @param page 参数集
     * @param userDTO 查询参数列表
     * @return 用户集合
     */
    @ApiOperation(value = "分页查询用户")
    @GetMapping("/user/page")
    public R getUserPage(@Validated PageDTO page, SysUserDTO userDTO) {
        return R.ok(PageUtil.resetPage(sysUserService.getUserWithRolePage(page, userDTO)));
    }

    @AnonymousAccess
    @ApiOperation(value = "通过角色标识分页查询用户")
    @GetMapping("/user/listByRoleCode")
    public R listUsersByRoleCode(@Validated PageDTO page, String roleCode) {
        return R.ok(PageUtil.resetPage(sysUserService.listUsersByRoleCode(page, roleCode)));
    }

    /**
     * 通过ID查询用户信息
     * @param id ID
     * @return 用户信息
     */
    @GetMapping("/user/detail")
    public R user(@RequestParam Long id) {
        return R.ok(sysUserService.getUserVoById(id));
    }

    @PreAuthorize("@pms.hasPermission('sys_user_del')")
    @SysLog("删除用户")
    @ApiOperation(value = "删除用户")
    @PostMapping("/user/detele")
    public R userDel(@RequestParam Long id) {
        SysUserDO sysUser = sysUserService.getById(id);
        return R.ok(sysUserService.removeUserById(sysUser));
    }

    /**
     * 添加用户
     * @param userDto 用户信息
     * @return success/false
     */
    @SysLog("添加用户")
    @PostMapping("user/create")
    @PreAuthorize("@pms.hasPermission('sys_user_add')")
    public R user( SysUserDTO userDto) {
        return R.ok(sysUserService.saveUser(userDto));
    }

    /**
     * 更新用户信息
     * @param userDto 用户信息
     * @return R
     */
    @SysLog("更新用户信息")
    @PostMapping("user/update")
    @PreAuthorize("@pms.hasPermission('sys_user_edit')")
    public R updateUser(@Validated SysUserDTO userDto) {
        return R.ok(sysUserService.updateUser(userDto));
    }

    /**
     * 修改个人信息
     * @param userDto userDto
     * @return success/false
     */
    @SysLog("修改个人信息")
    @PutMapping("/edit")
    public R updateUserInfo(@Validated  SysUserDTO userDto) {
        return sysUserService.updateUserInfo(userDto);
    }

    @SysLog("修改密码")
    @ApiOperation(value = "修改密码")
    @PostMapping("/user/update/password")
    public R changeUserPassword(@RequestParam @Positive(message = "{id.positive}") Long id, @RequestBody @Validated ChangePasswordDTO validator) {
        sysUserService.changeUserPassword(id, validator);
        return R.ok();
    }

    /**
     * @param username 用户名称
     * @return 上级部门用户列表
     */
    @GetMapping("/ancestor/{username}")
    public R listAncestorUsers(@PathVariable String username) {
        return R.ok(sysUserService.listAncestorUsersByUsername(username));
    }



    @AnonymousAccess
    @ApiOperation(value = "刷新token")
    @GetMapping(value = "/user/refreshToken")
    public R refreshToken(HttpServletRequest request) {
        return sysUserService.refreshToken(request);
    }


    @AnonymousAccess
    @ApiOperation(value = "登录")
    @PostMapping(value = "/user/login")
    public R login(@Validated LoginDTO loginDTO, HttpServletRequest request) {
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        SysUserVO sysUser = sysUserService.getSysUserByUsername(username);
        if (sysUser == null){
            throw new UsernameNotFoundException("用户名或密码错误");
        }
        UserDetails userDetails = fastUserDetailsService.loadUserByUsername(username);
        if (!new BCryptPasswordEncoder().matches(password, userDetails.getPassword())) {
            return R.failed("密码不正确");
        }
        if (!userDetails.isEnabled()){
            return R.failed("账号已被禁用");
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = jwtTokenUtil.generateToken(userDetails);
        //保存在线用户
        fastOnlineUserService.save((FastUser) authentication.getPrincipal(),token,request);
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", ValueUtil.tokenHead);
        if (ValueUtil.singleLogin) {
            //踢掉之前已经登录的token
            fastOnlineUserService.checkLoginOnUser(userDetails.getUsername(), token);
        }
        return R.ok(tokenMap);
    }

    @SysLog("登出功能")
    @AnonymousAccess
    @ApiOperation(value = "登出功能")
    @PostMapping(value = "/user/logout")
    public R logout(HttpServletRequest request) {
        fastOnlineUserService.logout(jwtTokenUtil.getToken(request));
        return R.ok();
    }
}
